﻿using System;
using System.Security.Principal;
using DomainModel;
using Repository.Abstract;
using Services.Abstract;

namespace Services.Concrete
{
    public class RingService : Service<Ring>, IRingService
    {
        private readonly IRingRepository _ringRepository;

        public RingService(IRingRepository ringRepository)
            : base(ringRepository)
        {
            _ringRepository = ringRepository;
        }

        public RingService(IRingRepository ringRepository, IPrincipal currentUser, IPermissionService permissionService)
            : base(ringRepository, currentUser, permissionService)
        {
            _ringRepository = ringRepository;
        }

        #region IRingService Members

        public Ring GetRingByPairNo(int pairNo)
        {
            if (pairNo < 1 || pairNo > 7)
            {
                throw new Exception("Неверно указан номер пары.");
            }

            return _ringRepository.GetRingByPairNo(pairNo);
        }

        public string GetPairBeginTime(int pairNo)
        {
            if (pairNo < 1 || pairNo > 7)
            {
                throw new Exception("Неверно указан номер пары.");
            }

            Ring ring = GetRingByPairNo(pairNo);
            if (ring != null)
                return ring.BeginTime.ToShortTimeString();
            return "";
        }

        public string GetPairEndTime(int pairNo)
        {
            if (pairNo < 1 || pairNo > 7)
            {
                throw new Exception("Неверно указан номер пары.");
            }

            Ring ring = GetRingByPairNo(pairNo);
            if (ring != null)
                return ring.EndTime.ToShortTimeString();
            return "";
        }

        public int GetPairNoByTime(DateTime time)
        {
            return _ringRepository.GetPairNoByTime(time);
        }

        public new void Delete(Ring ring)
        {
            if (!PermissionService.CanCUDRings())
                throw new Exception("Недостаточно прав для CUD операций со звонками.");

            base.Delete(ring);
        }

        public new void SaveOrUpdate(Ring ring)
        {
            if (!PermissionService.CanCUDRings())
                throw new Exception("Недостаточно прав для CUD операций со звонками.");

            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }

            if (ring.BeginTime >= ring.EndTime)
            {
                throw new Exception("Пара не может закончиться до того, как началась.");
            }

            // есть ли пары, которые идут во время начала этой пары?
            int p = GetPairNoByTime(ring.BeginTime);
            if (p > 0 && p != ring.PairNo)
            {
                throw new Exception(ring.PairNo + "-я пара не может начаться во время " + p + "-ой пары.");
            }

            // есть ли пары, которые идут во время конца этой пары?
            p = GetPairNoByTime(ring.EndTime);
            if (p > 0 && p != ring.PairNo)
            {
                throw new Exception(ring.PairNo + "-я пара не может закончиться во время " + p + "-ой пары.");
            }

            // если пара не первая - то она должна начинать после окончания предыдущей
            if (ring.PairNo > 1)
            {
                Ring r = GetRingByPairNo(ring.PairNo - 1);
                if (r != null)
                {
                    if (ring.BeginTime < r.EndTime)
                    {
                        throw new Exception(ring.PairNo + "-я пара не может начаться до конца " + r.PairNo + "-ой пары.");
                    }
                }
            }

            //если пара не последняя - то она должна заканчиваться до начала предыдущей
            if (ring.PairNo < 7)
            {
                Ring r = GetRingByPairNo(ring.PairNo + 1);
                if (r != null)
                {
                    if (ring.EndTime > r.BeginTime)
                    {
                        throw new Exception(ring.PairNo + "-я пара не может закончиться после начала " + r.PairNo +
                                            "-ой пары.");
                    }
                }
            }

            Ring oldRing = GetRingByPairNo(ring.PairNo);

            if (oldRing == null)
            {
                base.SaveOrUpdate(ring);
            }
            else
            {
                oldRing.BeginTime = ring.BeginTime;
                oldRing.EndTime = ring.EndTime;

                base.SaveOrUpdate(oldRing);
            }
        }

        #endregion
    }
}